package com.haikesi.api.user.service.impl;

import com.haikesi.api.base.*;
import com.haikesi.api.base.Error;
import com.haikesi.api.menuauthority.domain.po.MenuAuthorityPO;
import com.haikesi.api.menuauthority.domain.vo.MenuAuthorityTreeSearchVO;
import com.haikesi.api.menuauthority.domain.vo.MenuAuthorityTreeVO;
import com.haikesi.api.menuauthority.domain.vo.MenuAuthorityVO;
import com.haikesi.api.menuauthority.service.IMenuAuthorityService;
import com.haikesi.api.role.domain.vo.RoleVO;
import com.haikesi.api.user.dao.UserDao;
import com.haikesi.api.user.dao.UserRoleDao;
import com.haikesi.api.user.domain.po.UserPO;
import com.haikesi.api.user.domain.po.UserRolePO;
import com.haikesi.api.user.domain.vo.*;
import com.haikesi.exception.BusinessException;
import com.haikesi.util.LogApiUtils;
import com.haikesi.util.Uuid;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.haikesi.api.user.service.IUserService;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @version V1.0
 * @ClassName: UserService
 * @author: zqy
 * @date: 2019年4月28日 上午9:19:18
 * @Copyright: 2019 重庆海克斯科技有限公司.
 * 注意：本内容仅限于重庆海克斯科技有限公司内部传阅，禁止外泄以及用于其他的商业目
 */
@Service
@Transactional
public class UserServiceImpl implements IUserService {
    @Autowired
    private UserDao userDao;
    @Autowired
    private UserRoleDao userRoleDao;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private IMenuAuthorityService menuAuthorityService;

    @Override
    public List<UserVO> getList(UserSearchVO searchVO) {
        UserPO po=new UserPO();
        if(po.getUser()==null){
            searchVO.setOrganizationId("");
            return userDao.getList(searchVO);
        }
        searchVO.setOrganizationId(po.getUser().getOrganizationId());
        if(po.getUser().getIsAdmin()==1){
            searchVO.setOrganizationId("");
        }
        return userDao.getList(searchVO);
    }

    @Override
    public String create(UserSaveVO userSaveVO) {
        UserPO userPO = new UserPO();
        BeanUtils.copyProperties(userSaveVO, userPO);

        Example example = new Example(UserPO.class);
        example.and().andEqualTo("loginName", userPO.getLoginName());
        List<UserPO> list = userDao.selectByExample(example);
        if (!list.isEmpty()) {
            throw new BusinessException(Type.EXIST_ERROR, ErrorTools.ErrorAsArrayList(new Error("loginName", "用户名已存在")));
        }
        userPO.preInsert();
        int i = userDao.insertSelective(userPO);
        if (i == Constants.SQL_RETUN_SUCCESS) {
            new BusinessException(Type.EXCEPTION_FAIL);
        }
        //角色不为空需要添加角色
        if(StringUtils.isNotBlank(userSaveVO.getRoleId())){
            UserRolePO userRolePO=new UserRolePO();
            userRolePO.setRoleId(userSaveVO.getRoleId());
            userRolePO.setUserId(userPO.getId());
            userRoleDao.insertSelective(userRolePO);
        }
        return userPO.getId();
    }

    @Override
    public void update(UserUpdateVO updateVO) {
        UserPO po = new UserPO();
        BeanUtils.copyProperties(updateVO, po);
        UserPO userPO = userDao.selectByPrimaryKey(po.getId());
        if (userPO == null) {
            throw new BusinessException(Type.NOT_FOUND_ERROR, ErrorTools.ErrorAsArrayList(new Error("id", "用户不存在")));
        }
        po.preUpdate();
        int i = userDao.updateByPrimaryKeySelective(po);
        if (i == Constants.SQL_RETUN_SUCCESS) {
            throw new BusinessException(Type.EXCEPTION_FAIL);
        }
        if(StringUtils.isNotBlank(updateVO.getRoleId())){
            UserRolePO userRolePO=new UserRolePO();
            userRolePO.setRoleId(updateVO.getRoleId());
            userRolePO.setUserId(userPO.getId());
            userRoleDao.updateRoleId(userRolePO);
        }
    }

    @Override
    public void delete(String id) {
        if (StringUtils.isBlank(id)) {
            throw new BusinessException(Type.FORMAT_EXCEPTION);
        }
        UserPO userPO = userDao.selectByPrimaryKey(id);
        if (userPO == null) {
            throw new BusinessException(Type.NOT_FOUND_ERROR, ErrorTools.ErrorAsArrayList(new Error("id", "用户不存在")));
        }
        UserPO po = new UserPO();
        po.setId(id);
        po.preDelete();
        int i = userDao.updateByPrimaryKeySelective(po);
        if (i == Constants.SQL_RETUN_SUCCESS) {
            throw new BusinessException(Type.EXCEPTION_FAIL);
        }
    }

    @Override
    public UserLoginResVO login(UserLoginReqVO userLoginReqVO) {
        Example example = new Example(UserPO.class);
        UserPO sysUserQuery = new UserPO();
        BeanUtils.copyProperties(userLoginReqVO, sysUserQuery);
        example.and().andEqualTo(sysUserQuery);
        UserPO userPO = userDao.selectOneByExample(example);
        if (userPO == null) {
            throw new BusinessException(Type.NOT_FOUND_ERROR, ErrorTools.ErrorAsArrayList(new Error("loginName", "用户不存在")));
        }
        if (userPO.isDelFlag()) {
            throw new BusinessException(Type.NOT_FOUND_ERROR, ErrorTools.ErrorAsArrayList(new Error("loginName", "用户被删除")));
        }
        if (userPO.isDisableFlag()) {
            throw new BusinessException(Type.NOT_FOUND_ERROR, ErrorTools.ErrorAsArrayList(new Error("loginName", "用户已被禁用")));
        }
        if (!userLoginReqVO.getUserPassword().equalsIgnoreCase(userPO.getUserPassword())) {
            throw new BusinessException(Type.PARAM_VALIDATE_FAIL, ErrorTools.ErrorAsArrayList(new Error("password", "密码错误")));
        }

        RoleVO roleVO=userDao.getRoleByUserId(userPO.getId());
        if(roleVO==null){
            throw new BusinessException(Type.NOT_FOUND_ERROR, ErrorTools.ErrorAsArrayList(new Error("role", "用户没有角色权限")));
        }
        if(StringUtils.isBlank(roleVO.getOrganizationId())){
            throw new BusinessException(Type.NOT_FOUND_ERROR, ErrorTools.ErrorAsArrayList(new Error("organization", "用户没有机构")));
        }

        //修改登录时间和ip
        userPO.preUpdate();
        userDao.updateByPrimaryKeySelective(userPO);

        UserLoginResVO vo = new UserLoginResVO();
        BeanUtils.copyProperties(userPO, vo);
        vo.setTicket(Uuid.getUUID());
        long effective_millisecond = 5 * 60 * 1000;//5分钟
        long expire = System.currentTimeMillis() + effective_millisecond;
        vo.setExpire(expire);
        redisUtils.set(vo.getTicket(), vo.getId(), effective_millisecond, TimeUnit.MILLISECONDS);
        //添加登陆日志
        LogApiUtils.add_Login_Log(userLoginReqVO.getLoginIp(),null,userLoginReqVO.getLoginName(),userPO.getId());
        return vo;
    }

    @Override
    public UserTokenResVO getToken(String ticket) {
        if (!redisUtils.hasKey(ticket)) {
            throw new BusinessException(Type.PARAM_VALIDATE_FAIL, ErrorTools.ErrorAsArrayList(new Error("ticket", "凭证不正确,请重新申请")));
        }
        String userId = redisUtils.get(ticket);
        UserPO userPO = userDao.selectByPrimaryKey(userId);
        if (userPO == null) {
            throw new BusinessException(Type.PARAM_VALIDATE_FAIL, ErrorTools.ErrorAsArrayList(new Error("token", "用户不存在")));
        }
        if (userPO.isDelFlag()) {
            throw new BusinessException(Type.PARAM_VALIDATE_FAIL, ErrorTools.ErrorAsArrayList(new Error("token", "用户被删除")));
        }
        if (userPO.isDisableFlag()) {
            throw new BusinessException(Type.PARAM_VALIDATE_FAIL, ErrorTools.ErrorAsArrayList(new Error("token", "用户已被禁用")));
        }

        String token = Uuid.getUUID();


        User userSession = new User();
        BeanUtils.copyProperties(userPO, userSession);
        userSession=encapsulationUser(userSession);

        UserTokenResVO tokenResVO = new UserTokenResVO();
        tokenResVO.setToken(token);
        long effective_millisecond = 12 * 60 * 60 * 1000;//12小时
        long expire = System.currentTimeMillis() + effective_millisecond;
        tokenResVO.setExpireTime(new Date(expire));
        tokenResVO.setEffectiveMillisecond(effective_millisecond);
        String old = (String) ThreadLocalUtil.get(Constants.TOKEN_PARAM_NAME + userId);
        if (old != null && redisUtils.hasKey(old)) {
            redisUtils.delete(old);
        }
        redisUtils.delete(ticket);
        ThreadLocalUtil.put(Constants.TOKEN_PARAM_NAME + userId, token);
        ThreadLocalUtil.put(Constants.TOKEN_SESSION_NAME + userId, userSession);
        redisUtils.set(token, userSession, effective_millisecond, TimeUnit.MILLISECONDS);
        return tokenResVO;
    }

    @Override
    public UserTokenResVO refreshToken(String token) {
        User user = redisUtils.get(token);
        if (user == null) {
            throw new BusinessException(Type.NOT_FOUND_ERROR, ErrorTools.ErrorAsArrayList(new Error("token", "签名不存在")));
        }
        UserPO userPO = userDao.selectByPrimaryKey(user.getId());
        if (userPO == null) {
            throw new BusinessException(Type.PARAM_VALIDATE_FAIL, ErrorTools.ErrorAsArrayList(new Error("token", "用户不存在")));
        }
        if (userPO.isDelFlag()) {
            throw new BusinessException(Type.PARAM_VALIDATE_FAIL, ErrorTools.ErrorAsArrayList(new Error("token", "用户被删除")));
        }
        if (userPO.isDisableFlag()) {
            throw new BusinessException(Type.PARAM_VALIDATE_FAIL, ErrorTools.ErrorAsArrayList(new Error("token", "用户已被禁用")));
        }
        String newToken = Uuid.getUUID();
        User userSession = new User();
        BeanUtils.copyProperties(userPO, userSession);
        userSession=encapsulationUser(userSession);

        UserTokenResVO userTokenResVO = new UserTokenResVO();
        userTokenResVO.setToken(newToken);
        long effective_millisecond = 12 * 60 * 60 * 1000;//12小时
        long expire = System.currentTimeMillis() + effective_millisecond;
        userTokenResVO.setExpireTime(new Date(expire));
        userTokenResVO.setEffectiveMillisecond(effective_millisecond);
        String old = (String) ThreadLocalUtil.get(Constants.TOKEN_PARAM_NAME + userPO.getId());
        if (old != null && redisUtils.hasKey(old)) {
            redisUtils.delete(old);
        }
        ThreadLocalUtil.put(Constants.TOKEN_PARAM_NAME + userPO.getId(), token);
        ThreadLocalUtil.put(Constants.TOKEN_SESSION_NAME + userPO.getId(), userSession);
        redisUtils.delete(token);
        redisUtils.set(newToken, userSession, effective_millisecond, TimeUnit.MILLISECONDS);
        return userTokenResVO;
    }

    @Override
    public List<MenuAuthorityVO> getButtonMenuList() {
        MenuAuthorityPO po=new MenuAuthorityPO();
        User user=po.getUser();
        List<MenuAuthorityVO> rList=new ArrayList<>();
        if(user==null){
            return rList;
        }
        List<MenuAuthorityVO> rdList=user.getMenuAuthorityList();
        if(rdList==null||rdList.size()<1){
            return  rList;
        }
        for (MenuAuthorityVO vo:rdList ) {
            if(vo.getAuthorityType()!=null && vo.getAuthorityType()==2){
                rList.add(vo);
            }
        }
        return rList;
    }

    @Override
    public String getOrg(String id) {
        return userDao.getOrg(id);
    }

    @Override
    public List<MenuAuthorityTreeVO> menuTree( String isMenu) {
        MenuAuthorityPO po=new MenuAuthorityPO();
        User user=po.getUser();
        if(StringUtils.isNotBlank(isMenu)&&isMenu.equals("1")&&user.getIsAdmin()==1){
            return  menuAuthorityService.getTreeList(new MenuAuthorityTreeSearchVO());
        }
        List<MenuAuthorityTreeVO> rList=new ArrayList<>();
        if(user==null){
            return rList;
        }
        List<MenuAuthorityVO> rdList=user.getMenuAuthorityList();
        if(rdList==null||rdList.size()<1){
            return  rList;
        }

        List<MenuAuthorityTreeVO> list=new ArrayList<>();
        for (MenuAuthorityVO vo:rdList ) {
            if(vo.getAuthorityType()==null || vo.getAuthorityType()==2){
                continue;
            }
            MenuAuthorityTreeVO treeVO=new MenuAuthorityTreeVO();
            BeanUtils.copyProperties(vo, treeVO);
            list.add(treeVO);
        }
        HashMap<String,MenuAuthorityTreeVO> map=new HashMap<>();
        for (MenuAuthorityTreeVO vo:list) {
            map.put(vo.getId(),vo);
        }
        for (MenuAuthorityTreeVO vo:list) {
            if(vo.getParentId().equals("0")){
                rList.add(vo);
            }else {
                MenuAuthorityTreeVO parentVO=map.get(vo.getParentId());
                if(parentVO==null){
                    continue;
                }
                if(parentVO.getChildrens()==null){
                    parentVO.setChildrens(new ArrayList<>());
                }
                parentVO.getChildrens().add(vo);
            }
        }
        return rList;
    }

    @Override
    public void updatePassword(UserUpdatePasswordVO updateVO) {
        UserPO po=new UserPO();
        if(StringUtils.isBlank(updateVO.getId())){
            updateVO.setId(po.getUser().getId());
        }
        po=userDao.selectByPrimaryKey(updateVO.getId());
        if(po==null){
            throw new BusinessException(Type.PARAM_VALIDATE_FAIL, ErrorTools.ErrorAsArrayList(new Error("updatePassword", "当前用户不存在")));
        }
        if(!po.getUserPassword().equals(updateVO.getOldUserPassword())){
            throw new BusinessException(Type.PARAM_VALIDATE_FAIL, ErrorTools.ErrorAsArrayList(new Error("updatePassword", "旧密码不匹配")));
        }
        po.setUserPassword(updateVO.getUserPassword());
        po.preUpdate();
        userDao.updateByPrimaryKeySelective(po);
    }

    @Override
    public void cleanToken(UserTokenReqVO userTokenReqVO) {
        if(!redisUtils.hasKey(userTokenReqVO.getToken())){
            throw new BusinessException(Type.PARAM_VALIDATE_FAIL, ErrorTools.ErrorAsArrayList(new Error("token", "token不存在")));
        }
        redisUtils.delete(userTokenReqVO.getToken());
    }



    private User encapsulationUser(User userSession) {
        //需要封装菜单 权限 机构角色在用户缓存里面
         RoleVO roleVO=userDao.getRoleByUserId(userSession.getId());
         if(userSession.getLoginName().equals("hex")){
             userSession.setIsAdmin(1);
         }else{
             userSession.setIsAdmin(0);
         }
         userSession.setOrganizationId(roleVO.getOrganizationId());
         userSession.setRoleId(roleVO.getId());
         userSession.setMenuAuthorityList(userDao.getMenuAuthorityByRoleId(roleVO.getId()));
         userSession.setResourecesList(userDao.getResourecesByRoleId(roleVO.getId()));
        return userSession;
    }
}
